package com.lwl.blue.commont.aop;

import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
import com.google.common.base.CaseFormat;
import com.lwl.blue.commont.enums.PowerDataTypeEnum;
import com.lwl.blue.commont.utils.UserContextUtil;
import com.lwl.blue.vo.LoginUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.*;

/**
 * 新增修改拦截器
 *
 * @author: 蓝文良
 * @Date: 2022 04:2022/4/1
 */

@Slf4j
@Component
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class EditDataInterceptor extends AbstractSqlParserHandler implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        LoginUserInfo user = UserContextUtil.getUser();
        if (Objects.isNull(user)) {
            return invocation.proceed();
        }
        if (invocation.getTarget() instanceof ResultSetHandler) {
            if (PowerDataTypeEnum.NOT_SELECT.getValue() != user.getPowerDataType()) {
                return invocation.proceed();
            }
            return select(invocation);
        }
        return invocation.proceed();
    }

    /**
     * 切记配置，否则当前拦截器不会加入拦截器链
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    /**
     * 自定义配置写入，没有自定义配置的可以直接置空此方法
     *
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {

    }

    private Object select(Invocation invocation) throws Throwable {
        List resList = new ArrayList();
        DefaultResultSetHandler defaultResultSetHandler = (DefaultResultSetHandler) invocation.getTarget();
        MetaObject metaStatementHandler = SystemMetaObject.forObject(defaultResultSetHandler);
        MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("mappedStatement");
        //获取节点属性的集合
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();
        //获取mybatis返回的实体类类型名
        int resultMapCount = resultMaps.size();
        Statement statement = (Statement) invocation.getArgs()[0];
        ResultSet resultSet = statement.getResultSet();
        if (resultMapCount < 1
                || resultSet == null) {
            return invocation.proceed();
        }
        Class<?> resultType = resultMaps.get(0).getType();
        Set<String> powerSet = new HashSet<>();
        Field[] fields = resultType.getDeclaredFields();
        for (Field f : fields) {
            boolean annotation = f.isAnnotationPresent(PowerFieldInterface.class);
            if (annotation) {
                powerSet.add(f.getName());
            }
        }
        //不存在注解
        if (CollectionUtils.isEmpty(powerSet)) {
            return invocation.proceed();
        }
        //获得对应列名
        ResultSetMetaData rsmd = resultSet.getMetaData();
        List<String> columnList = new ArrayList<String>();
        for (int i = 1; i <= rsmd.getColumnCount(); i++) {
            columnList.add(rsmd.getColumnName(i));
        }
        while (resultSet.next()) {
            LinkedHashMap<String, Object> resultMap = new LinkedHashMap<String, Object>();
            for (String colName : columnList) {
                String colNameFormat = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, colName);
                resultMap.put(colNameFormat, resultSet.getString(colName));
                //判断存在就制空
                if (powerSet.contains(colNameFormat)) {
                    resultMap.put(colNameFormat, null);
                }
            }
            Object o = JSONObject.parseObject(JSONObject.toJSONString(resultMap), resultType);
            //将转换后的map转换为实体类中
            resList.add(o);

        }
        return resList;

    }
}
